//
// Created by yycs0 on 25-2-12.
//
#include <chrono>
#include "PushBoxGame.h"
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
static char* stepTab[] = {"^","<","none",">","v"};
int levelIndex = 0;
const int screenWidth  = 2000;
const int screenHeight = 1000;
double MAX_X = 10;
double MAX_Y = 10;
int OFFSET_X = 0;
std::vector<std::vector<std::vector<char>>> grids;
std::vector<std::string> titles;
State gstate;
MapInfo gmapInfo;
std::vector<std::vector<char>> ggrid;
inline float RCX(double x){
    return (x-OFFSET_X) * MAX_X/screenWidth;
}
inline float RCY(double y){
    return y *MAX_Y/screenHeight;
}
inline float CX(double x){
    return x * screenWidth/MAX_X+OFFSET_X;
}
inline float CY(double y){
    return  y * screenHeight/MAX_Y;
}
inline float CDX(double dx){
    return dx * screenWidth/MAX_X;
}
inline float CDY(double dy){
    return dy * screenHeight/MAX_Y;
}
void setMaxXY()
{
    MAX_Y = ggrid.size();
    MAX_X = 2*MAX_Y;
    OFFSET_X = CDX((MAX_X - ggrid[0].size())/2);
}
void DisplayPushBox()
{
    for(int i = 0; i < ggrid.size(); ++i)
    {
        for(int j = 0; j < ggrid[0].size(); ++j)
        {
            if(ggrid[i][j] == '#')
            {
                DrawRectangle(CX(j),CY(i),CDX(1),CDY(1),BLACK);
            }
            if(ggrid[i][j] == 'T')
            {
                DrawRectangleLines(CX(j),CY(i),CDX(1),CDY(1),WHITE);
                DrawLine(CX(j),CY(i),CX(j+1),CY(i+1),BLACK);
                DrawLine(CX(j+1),CY(i),CX(j),CY(i+1),BLACK);
            }
        }
    }
    for(int i = 0; i < gstate.boxx.size(); ++i)
    {
        DrawRectangle(CX(gstate.boxx[i]),CY(gstate.boxy[i]),CDX(1),CDY(1),CLITERAL(Color){ 0, 255, 0, 255 });
        DrawRectangleLines(CX(gstate.boxx[i]),CY(gstate.boxy[i]),CDX(1),CDY(1),WHITE);
    }
    DrawCircle(CX(gstate.px+0.5),CY(gstate.py+0.5),CDX(0.5),CLITERAL(Color){ 0, 0, 255, 255 });
    if(isRight(gstate, ggrid, gmapInfo))
    {
        DrawText("Right!",screenWidth/2,screenHeight/2,40,RED);
    }
    DrawText(titles[levelIndex].c_str(),OFFSET_X,10,40,RED);
}
void MouseButtonPress() {
    if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
        // 获取鼠标当前位置
        Vector2 mousePosition = GetMousePosition();
        double sx = RCX(mousePosition.x);
        double sy = RCY(mousePosition.y);
        TraceLog(LOG_INFO, "Mouse button pressed at: (%f, %f)", sx, sy);
        int idxx = static_cast<int>(sx);
        int idxy = static_cast<int>(sy);
        if((idxx == gstate.px && std::abs(idxy-gstate.py) == 1) || (std::abs(idxx-gstate.px) == 1 && idxy == gstate.py))
        {
            Action action;
            action.dx = idxx-gstate.px;
            action.dy = idxy-gstate.py;
            action.type = -1;
            if(isAction(action, gstate, ggrid))
            {
                gstate = move(action, gstate, ggrid);
            }
        }
    }
}
char HinsString[500];
void DisplayMainUI();
void DisplaySelectSCUI();
int UIState = 0;
void DisplayUI()
{
    if(UIState == 0)
    {
        DisplayMainUI();
    }else if(UIState == 1)
    {
        DisplaySelectSCUI();
    }else if(UIState == 2)
    {
    }
}
int selectBaseIdx = 0;
void DisplaySelectSCUI()
{
    DrawRectangle(screenWidth-20,0,320,screenHeight,GRAY);
    for(int i = 0; i < 100; ++i)
    {
        if (GuiButton((Rectangle){ screenWidth-20, float(i*50), 100, 50 }, ""))
        {
            levelIndex = i+selectBaseIdx;
            ggrid = getMap(grids[levelIndex], gstate, gmapInfo);
            UIState = 0;
        }
        DrawText(std::to_string(i+selectBaseIdx).c_str(),screenWidth-20, i*50+10,30,BLACK);
    }
    if (GuiButton((Rectangle){ screenWidth+100, 0, 100, 50 }, ""))
    {
        selectBaseIdx += 20;
    }
    DrawText("Next",screenWidth+100, 0+10,30,BLACK);
    if (GuiButton((Rectangle){ screenWidth+100, 50, 100, 50 }, ""))
    {
        selectBaseIdx -= 20;
        if(selectBaseIdx < 0)
        {
            selectBaseIdx = 0;
        }
    }
    DrawText("Prev",screenWidth+100, 50+10,30,BLACK);
    if (GuiButton((Rectangle){ screenWidth+100, 100, 100, 50 }, ""))
    {
        UIState = 0;
    }
    DrawText("Return",screenWidth+100, 100+10,30,BLACK);
}
void DisplayMainUI()
{
    DrawRectangle(screenWidth-20,0,320,screenHeight,GRAY);
    DrawText(HinsString, screenWidth-20, 100, 30, BLACK);
    if (GuiButton((Rectangle){ screenWidth-20, 50, 100, 50 }, ""))
    {
        auto sol = SolvePushBox(gstate, ggrid, gmapInfo);
        if(sol.empty())
        {
            sprintf(HinsString, "No Solution");
        }else{
            char *p = HinsString;
            p += sprintf(HinsString, "%d steps\n", sol.size());
            for(int i = 0; i < sol.size(); i++){
                if((i+1)%8==0)
                {
                    p += sprintf(p, "%s\n", stepTab[sol[i].dx+sol[i].dy*2+2]);
                }else{
                    p += sprintf(p, "%s ", stepTab[sol[i].dx+sol[i].dy*2+2]);
                }
            }
        }
    }
    DrawText("Solve",screenWidth-20,50+10,30,BLACK);
    if (GuiButton((Rectangle){ screenWidth+80, 50, 100, 50 }, ""))
    {
        UIState = 1;
    }
    DrawText("Level",screenWidth+80, 50+10,30,BLACK);
}
void DisplayWindow()
{
    InitWindow(screenWidth+300, screenHeight, "PushBox");
    SetTargetFPS(60);
    while (!WindowShouldClose())
    {
        BeginDrawing();
        ClearBackground(RAYWHITE);
        setMaxXY();
        DisplayPushBox();
        DisplayUI();
        MouseButtonPress();
        EndDrawing();
    }
    CloseWindow();
}

int main() {
    LoadLevelsFromFile("../696.xsb", grids, titles);
    std::cout<<grids.size()<<std::endl;
    ggrid = getMap(grids[levelIndex], gstate, gmapInfo);
    std::cout<<ggrid.size()<<std::endl;
    std::cout<<ggrid[0].size()<<std::endl;
    DisplayWindow();
    return 0;
}